

<template>
  <div style="height: 100%" :class="{ 'light-bg': pattern == '2' }">
    <!-- <div class="interval-tab">
      <span
        @click="
          changeSymbol({
            pair_ca: '0x49D37E82390348780444f40929bF233F72e40Ae6',
          })
        "
        >ETH</span
      >
      <span
        @click="
          changeSymbol({
            pair_ca: '0x7fe382B1C10Fc4bcB5b018701eb6CcC09eDBF83c',
          })
        "
        >USDT</span
      >
      <span @click="refreshTv"> 刷新1 </span>
    </div> -->
    <div>
      <div class="interval-tab">
        <span
          @click="changeInterval('1s')"
          :class="{ active: interval == '1s' }"
          >分时</span
        >
        <span @click="changeInterval('1')" :class="{ active: interval == '1' }"
          >1分</span
        >
        <span @click="changeInterval('5')" :class="{ active: interval == '5' }"
          >5分</span
        >
        <span
          @click="changeInterval('15')"
          :class="{ active: interval == '15' }"
          >15分</span
        >
        <span
          @click="changeInterval('60')"
          :class="{ active: interval == '60' }"
          >1小时</span
        >
        <span
          @click="changeInterval('240')"
          :class="{ active: interval == '240' }"
          >4小时</span
        >
        <span
          @click="changeInterval('720')"
          :class="{ active: interval == '720' }"
          >12小时</span
        >
        <span
          @click="changeInterval('1D')"
          :class="{ active: interval == '1D' }"
          >24小时</span
        >
      </div>
    </div>
    <div class="k-line-area">
      <div id="tv_chart_container" style="height: 100%"></div>
      <div class="loading-indicator" v-show="isLoadingTv">
        <div class="tv-spinner"></div>
      </div>
    </div>
    <div class="study-area">
      <div class="study-area-left">
        <span
          @click="setMainIndicator('MA')"
          :class="{ active: isCreateStudyMain['MA'] }"
          >MA</span
        >
        <span
          @click="setMainIndicator('EMA')"
          :class="{ active: isCreateStudyMain['EMA'] }"
        >
          EMA
        </span>
        <span
          @click="setMainIndicator('BOLL')"
          :class="{ active: isCreateStudyMain['BOLL'] }"
          >BOLL</span
        >
        <span
          @click="setMainIndicator('SAR')"
          :class="{ active: isCreateStudyMain['SAR'] }"
          >SAR</span
        >
      </div>
      |
      <div class="study-area-right">
        <span
          @click="setSubIndicator('VOL')"
          :class="{ active: isCreateStudySub['VOL'] }"
          >VOL</span
        >
        <span
          @click="setSubIndicator('MACD')"
          :class="{ active: isCreateStudySub['MACD'] }"
          >MACD</span
        >
        <span
          @click="setSubIndicator('KDJ')"
          :class="{ active: isCreateStudySub['KDJ'] }"
          >KDJ</span
        >
        <span
          @click="setSubIndicator('BOLL')"
          :class="{ active: isCreateStudySub['BOLL'] }"
          >BOLL</span
        >
        <span
          @click="setSubIndicator('RSI')"
          :class="{ active: isCreateStudySub['RSI'] }"
          >RSI</span
        >
        <span
          @click="setSubIndicator('OBV')"
          :class="{ active: isCreateStudySub['OBV'] }"
          >OBV</span
        >
        <span
          @click="setSubIndicator('TRIX')"
          :class="{ active: isCreateStudySub['TRIX'] }"
          >TRIX</span
        >
      </div>
    </div>
  </div>
</template>
<script setup>
console.log('kline-组件页面')
import { nextTick, onMounted, onUnmounted, reactive, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { init, dispose, utils, registerIndicator } from "../utils/echarts";
import * as api from "../api/api_path";
import data from "../api/data";
import { tE } from "../utils/flt";
import config from "../klineStyles";
import { useSocket } from "../utils/socket";
import uTimes from "../utils/times";
let chart = null;
const route = useRoute();
const pattern = route.query.pattern || 1;
const { socket, send, on, off } = useSocket("wss://stream.dexx.ai/stream", {});
const interval = ref("15");
const isLoadingTv = ref(false);
const symbolInfo = ref({
  pair_ca: "0x7fe382B1C10Fc4bcB5b018701eb6CcC09eDBF83c",
  chain_id: "8453",
});
const isCreateStudyMain = reactive({
  MA: false,
  EMA: false,
  BOLL: false,
  SAR: false,
});
const isCreateStudySub = reactive({
  BOLL: false,
  VOL: false,
  MACD: false,
  KDJ: false,
  TRIX: false,
  RSI: false,
  OBV: false,
});
window.updateWidget = updateWidget;
window.refreshTv = refreshTv;
onMounted(async () => {
  chart = init("tv_chart_container", {
    styles: {
      grid: config.grid(pattern),
      candle: config.candle(),
      yAxis: config.yAxis(pattern),
      xAxis: config.yAxis(pattern),
      separator: config.separator(pattern),
      indicator: config.indicator(),
    },
    locale: "zh-CN",
    customApi: {
      formatBigNumber: (value) => {
        return tE(value);
      },
    },
  });
  chart.setPriceVolumePrecision({
    pricePrecision: 17,
  });

  socket.on("open", (event) => {});
  socket.on("message", (res) => {
    res = JSON.parse(res);
    if (res && res.action === "connect") {
      socketKlineData();
    }
    if (res && res.data) {
      let data = res.data;
      if (res.channel == "token_kline" && data) {
        let kline = {};
        kline.open = kline.close;
        kline.time = Number(1e3 * data[0].timestamp);
        kline.close = data[0].close_price;
        kline.low = data[0].close_price;
        kline.high = data[0].close_price;
        kline.volume = data[0].volume;
        chart.updateData(kline);
      }
    }
  });
});
if (import.meta.env.MODE === "development") {
  // updateWidget(symbolInfo.value);
}

function changeInterval(time) {
  interval.value = time;
  updateWidget({ ...symbolInfo.value, kline_interval: time });
  closeSendKline();
  socketKlineData();
}
function changeSymbol(info) {
  updateWidget({
    ...symbolInfo.value,
    pair_ca: info.pair_ca,
    chain_id: "8453",
  });
  closeSendKline();
  socketKlineData();
}
async function updateWidget(params) {
  let prames = {
    pair_ca: params.pair_ca,
    chain_id: params.chain_id,
    from_timestamp: 1717291443,
    to_timestamp: Math.floor(Date.now() / 1000),
    limit: 100,
    kline_interval: uTimes(interval.value),
  };
  symbolInfo.value = prames;
  isLoadingTv.value = true;
  let klineHisList = await getKlineHistoryList(prames);
  isLoadingTv.value = false;
  chart.applyNewData(klineHisList, klineHisList.length > 0);
  chart.loadMore((timestamp) => {
    chart.applyMoreData(
      getKlineHistoryList({ ...prames, to_timestamp: timestamp }),
      true
    );
  });
  setMainIndicator("MA");
}
function closeSendKline() {
  socket.send(
    JSON.stringify({
      id: symbolInfo.value.id || "1",
      action: "unsubscribe",
      channel: "token_kline",
      data: {
        chain: symbolInfo.value.chain_id,
      },
    })
  );
}
function socketKlineData() {
  socket.send(
    JSON.stringify({
      id: "1",
      action: "subscribe",
      channel: "token_kline",
      data: {
        chain: symbolInfo.value.chain_id,
        address: symbolInfo.value.pair_ca,
        interval: uTimes(interval.value),
      },
    })
  );
}

// 获取历史数据
async function getKlineHistoryList(params) {
  let res = await api.tvs.quoteHis(params);
  let datas = res.data;
  let bars = [];
  for (let i = 0; i < datas.length; i++) {
    bars.push({
      timestamp: Number(1e3 * datas[i].timestamp),
      open: Number(datas[i].open),
      close: Number(datas[i].close),
      high: Number(datas[i].high),
      low: Number(datas[i].low),
      volume: Number(datas[i].volume),
    });
  }
  return bars;
}
//主图指标
function setMainIndicator(name) {
  isCreateStudyMain[name] = !isCreateStudyMain[name];
  chart.createIndicator(name, true, { id: "candle_pane" });
}

//副图指标添加
function setSubIndicator(name) {
  isCreateStudySub[name] = !isCreateStudySub[name];
  chart.createIndicator(name);
}
function refreshTv() {
  chart.scrollToRealTime();
}
onUnmounted(() => {
  dispose("chart");
});
</script>
<style lang="less" scoped>
.k-line-area {
  height: calc(100% - 82px);
  position: relative;
}
.study-area,
.interval-tab {
  color: #6d7280;
  height: 40px;
  display: flex;
  align-items: center;
  font-size: 12px;
  overflow: auto;
  white-space: nowrap;
  justify-content: center;
  &::-webkit-scrollbar {
    width: 0px; /* 对于垂直滚动条，设置宽度 */
    height: 0px; /* 对于水平滚动条，设置高度 */
  }
  span {
    display: inline-block;
    padding: 2px 8px 2px 8px;
    line-height: 24px;
    margin-left: 2px;
    text-align: center;
    // min-width: 53px;
    white-space: nowrap;
    border-radius: 6px;
    &:hover {
      cursor: pointer;
    }
    &.active {
      font-weight: bold;
    }
  }
}
.study-area {
  border-top: 1px solid #eee;
  position: fixed;
  left: 0;
  right: 0;
  // top: -20px;
  bottom: 0;
  z-index: 9999;
  background: #fff;

  .study-area-left {
    // width: 164px;
    padding: 0 16px;
    span {
      padding: 2px 0;
      margin-right: 10px;
      color: #a0a6b2;
      &:last-child {
        margin-right: 0;
      }
      // margin-left: 8px;
    }
  }
  .study-area-right {
    width: calc(100% - 186px);
    overflow: auto;
    display: flex;
    margin-left: 8px;
    color: #a0a6b2;
    &::-webkit-scrollbar {
      scrollbar-width: none;
      scrollbar-color: none;
      width: 0; /* 对于垂直滚动条，设置宽度 */
      height: 0; /* 对于水平滚动条，设置高度 */
    }
    span {
      padding: 2px 0;
      margin-right: 8px;
      color: #a0a6b2;
      &:last-child {
        padding-right: 16px;
      }
    }
  }
  span {
    &.active {
      font-weight: normal;
      color: #1b1e26;
    }
  }
}
.interval-tab {
  background: #fff;
  border-bottom: 1px solid #eee;
  span {
    &.active {
      background-color: #f0f3fa;
    }
  }
}

.light-bg {
  background-color: #212530;
  color: #ddd;
  .loading-indicator {
    background-color: rgba(33, 37, 48, 0.4);
  }
  .study-area {
    border-top: 1px solid #323c5d;
    background: #212530;
    span {
      &.active {
        color: #fff;
      }
    }
  }
  .interval-tab {
    border-bottom: 1px solid #323c5d;
    background: #212530;
    span {
      &.active {
        color: #fff;
        font-weight: bold;
        background: #292d3a;
      }
    }
  }
}

.loading-indicator {
  background: rgba(255, 255, 255, 0.4);
  height: 100%;
  left: 0;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  z-index: 1999;

  .tv-spinner {
    animation: tv-spinner__container-rotate-aLqboHuu 0.9s linear infinite;
    border-bottom: 4px solid #8797a533;
    border-left: 4px solid #8797a533;
    border-radius: 50%;
    border-right: 4px solid #8797a533;
    border-top: 4px solid #8797a533;

    border-left-color: rgba(255, 211, 32, 0.4); // rgba(225, 81, 81, 0.4);
    border-top-color: rgba(255, 211, 32, 0.4);
    height: 50px;
    left: calc(50% - 25px);
    margin: 0 auto;
    position: absolute;
    top: calc(50% - 25px);
    width: 50px;
  }
}

@keyframes tv-spinner__container-rotate-aLqboHuu {
  to {
    transform: rotate(1turn);
  }
}
</style>